package com.person.yhzs.util;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.LocalFileHeader;

import java.io.*;
import java.util.ArrayList;
import java.util.List;


public class ZipUtils {

    /**
     * 解压文件
     *
     * @param source   zip文件路径 E:/xx.zip
     * @param dest     E:/down
     * @param password 压缩包密码
     */
    public void decompressionZip(String source, String dest, String password) {
        try {
            File zipFile = new File(source);
            // 首先创建ZipFile指向磁盘上的.zip文件
            ZipFile zFile = new ZipFile(zipFile);
            // zFile.setFileNameCharset("GBK");
            // 解压目录
            File destDir = new File(dest);
            if (!destDir.exists()) {
                // 目标目录不存在时，创建该文件夹
                destDir.mkdirs();
            }
            if (zFile.isEncrypted()) {
                // 设置密码
                zFile.setPassword(password.toCharArray());
            }
            // 将文件抽出到解压目录(解压)
            zFile.extractAll(destDir.getAbsolutePath());
            List<FileHeader> headerList = zFile.getFileHeaders();
            List<File> extractedFileList = new ArrayList<File>();
            for (FileHeader fileHeader : headerList) {
                if (!fileHeader.isDirectory()) {
                    extractedFileList.add(new File(destDir, fileHeader.getFileName()));
                }
            }
            File[] extractedFiles = new File[extractedFileList.size()];
            extractedFileList.toArray(extractedFiles);
            for (File f : extractedFileList) {
                System.out.println(f.getAbsolutePath() + "文件解压成功!");
            }
        } catch (ZipException e) {
            e.printStackTrace();
        }


    }

    /**
     * 将inputStream解压到指定目录
     *
     * @param inputStream 文件流
     * @param outPath 输出目录
     * @throws IOException
     */
    public static void decompressionFile(InputStream inputStream, String outPath) throws IOException {
        //判断输出路径是否合法
        if (new File(outPath).isDirectory()) {
            //zip读取压缩文件
            ZipInputStream zipInputStream = new ZipInputStream(inputStream);
            //解压文件
            decompressionFile(outPath, zipInputStream);
            //关闭流
            zipInputStream.close();
            inputStream.close();
        } else {
            throw new RuntimeException("输出路径不合法!");
        }


    }

    /**
     * ZipInputStream是逐个目录进行读取，所以只需要循环
     * 循环将ZipInputStream 解压
     *
     * @param outPath
     * @param inputStream
     * @throws IOException
     */
    private static void decompressionFile(String outPath, ZipInputStream inputStream) {
        try {
            //读取一个目录
            LocalFileHeader nextEntry = inputStream.getNextEntry();
            //不为空进入循环
            while (nextEntry != null) {
                String name = nextEntry.getFileName();
                int index = name.lastIndexOf("/");
                String path = name.substring(0, index);
                File file = new File(outPath + path);
                //如果是目录，创建目录
                if (!file.exists()) {
                    file.mkdirs();
                }
                //文件则写入具体的路径中
                File fileOne = new File(outPath + name);
                if(!fileOne.exists()){
                    FileOutputStream fileOutputStream = new FileOutputStream(fileOne);
                    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
                    int n;
                    byte[] bytes = new byte[1024];
                    while ((n = inputStream.read(bytes)) != -1) {
                        bufferedOutputStream.write(bytes, 0, n);
                    }
                    //关闭流
                    bufferedOutputStream.close();
                    fileOutputStream.close();
                }
                //读取下一个目录，作为循环条件
                nextEntry = inputStream.getNextEntry();
            }
            //循环结束后关闭流
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }







}